iT邦幫忙

2024 iThome 鐵人賽

DAY 20
1

開始測試前,讓我們在元件中新增一些對外屬性,方便進行測試吧。( ´ ▽ ` )ノ

src\components\wrapper-physics\wrapper-physics.vue

...

<script setup lang="ts">
...

// #region Methods
defineExpose({
  ...

  bodyMap,
  bodyInfoMap,
});
// #endregion Methods
</script>

src\components\wrapper-physics\wrapper-physics-body.vue

...

<script setup lang="ts">
...

defineExpose({
  id,
  info,
});
</script>

完成測試

新增第一個測試案例吧。

src\components\wrapper-physics\wrapper-physics.spec.ts

import { mount } from '@vue/test-utils';
import { test, expect } from 'vitest';

import WrapperPhysics from './wrapper-physics.vue';

test('沒有任何子元素時 bodyMap 為空', () => {
  const wrapper = mount(WrapperPhysics);
  expect(wrapper).toBeDefined();

  const bodyMap = wrapper.vm.bodyMap;
  expect(bodyMap.size).toBe(0);
})
 RERUN  src/components/wrapper-physics/wrapper-physics.spec.ts x3

 ✓ src/components/wrapper-physics/wrapper-physics.spec.ts (2)
   ✓ 沒有任何子元素時 bodyMap 為空

順利通過。

讓我們加入更多註冊物體邏輯吧。◝( •ω• )◟

src\components\wrapper-physics\wrapper-physics.spec.ts

import { mount } from '@vue/test-utils';
import { test, expect } from 'vitest';
import { h } from 'vue';

import WrapperPhysics from './wrapper-physics.vue';
import WrapperPhysicsBody from './wrapper-physics-body.vue';

test('沒有任何子元素時 bodyMap 為空', () => {
  const wrapper = mount(WrapperPhysics);
  expect(wrapper).toBeDefined();

  const bodyMap = wrapper.vm.bodyMap;
  expect(bodyMap.size).toBe(0);
})

test('內部僅有非 body 元件子元素時 bodyMap 為空', () => {
  const wrapper = mount(WrapperPhysics, {
    slots: {
      default: '<div>安安</div>',
    },
  });
  expect(wrapper).toBeDefined();

  const bodyMap = wrapper.vm.bodyMap;
  expect(bodyMap.size).toBe(0);
})

test('bodyMap 數量必須相符 body 元件數量', () => {
  const wrapper = mount(WrapperPhysics, {
    slots: {
      default: [
        h(WrapperPhysicsBody),
        h(WrapperPhysicsBody),
      ],
    },
  });
  expect(wrapper).toBeDefined();

  const bodyMap = wrapper.vm.bodyMap;
  expect(bodyMap.size).toBe(2);
})

最後加入物理模擬相關測試。

src\components\wrapper-physics\wrapper-physics.spec.ts

...

test('start 後物體會移動', async () => {
  const wrapper = mount(WrapperPhysics, {
    slots: {
      default: [
        h(WrapperPhysicsBody),
        h(WrapperPhysicsBody),
      ],
    },
  });

  // 等待 bodyInfo 更新
  await delay(50);
  const bodyInfoMap = wrapper.vm.bodyInfoMap;

  bodyInfoMap.forEach((info) => {
    expect(info.offsetX).toBe(0);
    expect(info.offsetY).toBe(0);
  })

  wrapper.vm.start();
  await delay(500);

  bodyInfoMap.forEach((info) => {
    expect(info.offsetX).not.toBe(0);
    expect(info.offsetY).not.toBe(0);
  })
})

test('reset 會清空 bodyInfoMap', async () => {
  const wrapper = mount(WrapperPhysics, {
    props: {
      immediate: true,
    },
    slots: {
      default: [
        h(WrapperPhysicsBody),
        h(WrapperPhysicsBody),
      ],
    },
  });

  const bodyInfoMap = wrapper.vm.bodyInfoMap;
  await delay(500);

  expect(bodyInfoMap.size).toBe(2);

  wrapper.vm.reset();

  expect(bodyInfoMap.size).toBe(0);
})

test('isStatic 的物體完全不會移動', async () => {
  const wrapper = mount(WrapperPhysics, {
    props: {
      immediate: true,
    },
    slots: {
      default: [
        h(WrapperPhysicsBody, { isStatic: true }),
        h(WrapperPhysicsBody),
        h(WrapperPhysicsBody, { isStatic: true }),
      ],
    },
  });

  const bodyMap = wrapper.vm.bodyMap;
  const bodyInfoMap = wrapper.vm.bodyInfoMap;
  await delay(500);

  /** 所有靜止物體的 ID */
  const staticIds = [...bodyMap.entries()]
    .filter(([id, body]) => body.isStatic)
    .map(([id]) => id);

  [...bodyInfoMap.entries()].forEach(([id, info]) => {
    if (staticIds.includes(id)) {
      expect(info.offsetX).toBe(0);
      expect(info.offsetY).toBe(0);
    } else {
      expect(info.offsetX).not.toBe(0);
      expect(info.offsetY).not.toBe(0);
    }
  })
})

順利通過!✧*。٩(ˊᗜˋ*)و✧*。

 ✓ src/components/wrapper-physics/wrapper-physics.spec.ts (6) 1739ms
   ✓ 沒有任何子元素時 bodyMap 為空
   ✓ 內部僅有非 body 元件子元素時 bodyMap 為空
   ✓ bodyMap 數量必須相符 body 元件數量
   ✓ start 後物體會移動 579ms
   ✓ reset 會清空 bodyInfoMap 516ms
   ✓ isStatic 的物體完全不會移動 505ms

 Test Files  1 passed (1)
      Tests  6 passed (6)
   Start at  23:22:48
   Duration  2.12s

總結

  • 完成「物理包裝器」單元測試

以上程式碼已同步至 GitLab,大家可以前往下載:

GitLab - D20


上一篇
D19 - 物理包裝器:開發元件
下一篇
D21 - 物理包裝器:更多範例
系列文
要不要 Vue 點酷酷的元件?30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言